package com.ccp.dev.workflow.listener;

import com.ccp.dev.core.basic.consts.SystemConst;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.workflow.bpmconst.BpmConst;
import com.ccp.dev.workflow.dao.*;
import com.ccp.dev.workflow.model.ExecutionStack;
import com.ccp.dev.workflow.model.TaskFork;
import com.ccp.dev.workflow.model.TaskOpinion;
import com.ccp.dev.workflow.model.bpm.ProcessCmd;
import com.ccp.dev.workflow.service.BpmProStatusService;
import com.ccp.dev.workflow.service.BpmService;
import com.ccp.dev.workflow.service.ExecutionStackService;
import com.ccp.dev.workflow.service.TaskOpinionService;
import com.ccp.dev.workflow.service.bpm.thread.TaskThreadService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntityImpl;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * ClassDescribe:
 * 任务完成监听器
 * @author :wangcheng
 * Date: 2019-05-13
 */
@Component
public class TaskDeleteListener extends BaseTaskListener {
    @Resource
    private TaskOpinionService taskOpinionService;
    @Resource
    private BpmProStatusDao bpmProStatusDao;
    @Resource
    private BpmProStatusService bpmProStatusService;
    @Resource
    private ExecutionStackDao executionStackDao;
    @Resource
    private ExecutionStackService executionStackService;
    @Resource
    private TaskDao taskDao;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private HistoryService historyService;
    @Resource
    private TaskReadDao taskReadDao;
    @Resource
    private TaskService taskService;
    @Resource
    private BpmService bpmService;
    @Resource
    private HistoryActivityDao historyActivityDao;

    @Override
    protected void execute(DelegateTask delegateTask, String procDefId, String nodeId) {
        //2019-12-16 jyq新增，流转任务不进行处理
        if(delegateTask.getDescription().equals(TaskOpinion.STATUS_TRANSTO.toString())){
            return;
        }
        //获取当前任务的分发的令牌, value as T_1 or T_1_2
        String token = (String) delegateTask.getVariableLocal(TaskFork.TAKEN_VAR_NAME);
        if (token != null) {
            //放置会签线程，以使得在后续产生的任务中使用
            TaskThreadService.setToken(token);
        }

        //更新执行堆栈里的执行人员及完成时间等
        updateExecutionStack(delegateTask.getProcessInstanceId(), delegateTask.getTaskDefinitionKey(), token);
        //更新任务意见。
        updOpinion(delegateTask);
        //更新流程节点状态。
        updNodeStatus(nodeId, delegateTask);
        //更新历史节点
        setActHisAssignee(delegateTask);
        //删除任务已读记录
        taskReadDao.delByTaskId(delegateTask.getId());
    }

    /**
     * 更新执行堆栈里的执行人员及完成时间等
     *
     * @param instanceId
     *            流程实例ID
     * @param nodeId
     *            节点IDeas
     * @param token
     *            　令牌
     */
    private void updateExecutionStack(String instanceId, String nodeId, String token) {
        ExecutionStack executionStack = executionStackService.getLastestStack(instanceId, nodeId, token);
        if (executionStack != null) {
            SysUser curUser = (SysUser) ContextUtil.getCurrentUser();
            String userId = "";
            if (curUser != null) {
                userId = curUser.getUserId();
            } else {
                userId = SystemConst.SYSTEMUSERID;
            }
            executionStack.setAssignees(userId);
            executionStack.setEndTime(new Date());
            executionStackDao.update(executionStack);
        }

    }

    /**
     * 修改当前任务意见。
     *
     * @param delegateTask
     */
    private Long updOpinion(DelegateTask delegateTask) {
        TaskOpinion taskOpinion = taskOpinionService.getByTaskId(delegateTask.getId());

        if (taskOpinion == null){
            return 0L;
        }

        SysUser sysUser = (SysUser) ContextUtil.getCurrentUser();
        String userId = SystemConst.SYSTEMUSERID;
        String userName = SystemConst.SYSTEMUSERNAME;
        if (sysUser != null) {
            ProcessCmd cmd = TaskThreadService.getProcessCmd();
            //如果跳过不更改意见执行人。
            if (!cmd.isSkip()) {
                userId = sysUser.getUserId();
                userName = sysUser.getFullName();
                String approvalContent = cmd.getVoteContent();
                String attachment = cmd.getAttachment();
                taskOpinion.setOpinion(approvalContent);
                taskOpinion.setAttachment(attachment);
            } else {
                taskOpinion.setOpinion("同意(自动审批)");
            }
        }else{
            taskOpinion.setOpinion("系统(自动审批)");
        }
        taskOpinion.setExeUserId(userId);
        taskOpinion.setExeFullname(userName);

        ProcessCmd cmd = TaskThreadService.getProcessCmd();

        //获取流程意见。
        Short status = getStatus(cmd);
        taskOpinion.setCheckStatus(status);
        String fieldName = cmd.getVoteFieldName();
        if (StringUtil.isNotEmpty(fieldName)) {
            taskOpinion.setFieldName(fieldName);
        }
        taskOpinion.setEndTime(new Date());
        Long duration = taskOpinion.getEndTime().getTime()-taskOpinion.getStartTime().getTime();
        taskOpinion.setDurTime(duration);
        taskOpinionService.update(taskOpinion);

        return 0L;
    }

    /**
     * 更新流程节点的状态。
     *
     * @param nodeId
     * @param delegateTask
     */
    private void updNodeStatus(String nodeId, DelegateTask delegateTask) {
        boolean isMuliti = bpmService.isSignTask(delegateTask.getProcessDefinitionId(),nodeId);
        //非会签节点,更新节点的状态。
        if (!isMuliti) {
            Map<String, Object> map = runtimeService.getVariables(delegateTask.getProcessInstanceId());
            String procInstanceId = delegateTask.getProcessInstanceId();
            //更新节点状态。
            Short approvalStatus = (Short) map.get(BpmConst.NODE_APPROVAL_STATUS + "_" + delegateTask.getTaskDefinitionKey());
            bpmProStatusService.updStatus(procInstanceId, nodeId, approvalStatus);
        }
    }

    /**
     * 更新历史任务节点的执行人
     * @param delegateTask
     */
    private void setActHisAssignee(DelegateTask delegateTask) {
        List<HistoricActivityInstance> hisList = null;
        String procInstId = delegateTask.getProcessInstanceId();
        String activitiId = delegateTask.getTaskDefinitionKey();
        hisList = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInstId).activityId(activitiId).list();
        if (BeanUtils.isEmpty(hisList)) {
            return;
        }
        SysUser curUser = (SysUser) ContextUtil.getCurrentUser();
        if (curUser == null) {
            return;
        }
        String assignee = curUser.getUserId();
        for (HistoricActivityInstance hisActInst : hisList) {
            HistoricActivityInstanceEntityImpl hisActInstEntity = (HistoricActivityInstanceEntityImpl)hisActInst;
            //流转任务正常流转，即无别人干预
            if (TaskOpinion.STATUS_COMMON_TRANSTO.toString().equals(delegateTask.getDescription())) {
                assignee = delegateTask.getAssignee();
                //避免flowable中任务分配人与assignee一致，不重新分配问题
                taskService.setAssignee(delegateTask.getId(), "");
                taskService.setAssignee(delegateTask.getId(), assignee);
                hisActInstEntity.setAssignee(assignee);
            } else {
                //如果是当前任务的历史数据，任务执行人为空或者 执行人和当前人不一致，设置当前人为任务执行人。如果任务已结束（endTime不为空），那么就不需要更新记录了
                if(hisActInstEntity.getEndTime() == null || (hisActInstEntity.getTaskId()!=null && hisActInstEntity.getTaskId().equals(delegateTask.getId()))){
                    if (StringUtil.isEmpty(hisActInstEntity.getAssignee()) || !hisActInstEntity.getAssignee().equals(assignee)) {
                        //避免flowable中任务分配人与assignee一致，不重新分配问题
                        taskService.setAssignee(delegateTask.getId(), "");
                        taskService.setAssignee(delegateTask.getId(), assignee);
                        hisActInstEntity.setAssignee(assignee);
                    }
                }
            }
            historyActivityDao.update(hisActInstEntity);
        }
    }

    /**
     * 获取审批状态。
     *
     * @param cmd
     * @return
     */
    private Short getStatus(ProcessCmd cmd) {
        Short status = TaskOpinion.STATUS_AGREE;
        /**
         * 0，正常跳转。 1，驳回 2，驳回到发起人。
         */
        int isBack = cmd.isBack();
        boolean isRevover = cmd.isRecover();
        /*
         * 0=弃权,1=同意,2=反对,3=驳回, 4=追回, 5=会签通过, 6=会签不通过, 33=提交,34=再提交, 40=代提交
         */
        int vote = cmd.getVoteAgree();
        switch (isBack) {
            //正常
            case 0:
                switch (vote) {
                    case 0:
                        status = TaskOpinion.STATUS_ABANDON;
                        break;
                    case 1:
                        status = TaskOpinion.STATUS_AGREE;
                        break;
                    case 2:
                        status = TaskOpinion.STATUS_REFUSE;
                        break;
                    case 5:
                        status = TaskOpinion.STATUS_PASSED;
                        break;
                    case 6:
                        status = TaskOpinion.STATUS_NOT_PASSED;
                        break;
                    case 33:
                        status = TaskOpinion.STATUS_SUBMIT;
                        break;
                    case 34:
                        status = TaskOpinion.STATUS_RESUBMIT;
                        break;
                    case 40:
                        status = TaskOpinion.STATUS_REPLACE_SUBMIT;
                        break;
                }
                break;
            //驳回（追回)
            case 1:
                if (isRevover) {
                    status = TaskOpinion.STATUS_RECOVER;
                } else {
                    status = TaskOpinion.STATUS_REJECT;
                }
                break;
            //驳回（追回)到发起人。
            case 2:
                if (isRevover) {
                    status = TaskOpinion.STATUS_RECOVER_TOSTART;
                } else {
                    status = TaskOpinion.STATUS_REJECT_TOSTART;
                }
                break;
            case 4:
                status = TaskOpinion.STATUS_REJECT;
        }
        return status;
    }

    @Override
    protected int getScriptType() {
        return BpmConst.END_SCRIPT;
    }

    @Override
    protected int getBeforeScriptType() {
        return BpmConst.EndBeforeScript;
    }
}
